package org.infodavid.common.test.model;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;

import org.junit.Assert;

import com.thoughtworks.xstream.XStream;

/**
 * The Class CompareAssertions.
 */
public final class CompareAssertions {

	/**
	 * The Constructor.
	 */
	private CompareAssertions() {
		super();
	}

	/**
	 * Compare the two objects using XStream.
	 * @param arg0 the first object
	 * @param arg1 the second object
	 * @return true, if data contained in the object is equal
	 */
	public static boolean equals(final Object arg0, final Object arg1) {
		boolean result;

		if (arg0 == null && arg1 == null) {
			result = true;
		}
		else if (arg0 != null && arg1 == null || arg0 == null && arg1 != null) {
			result = false;
		}
		else if (arg0 != null && arg1 != null) {
			final XStream serializer = new XStream();

			result = serializer.toXML(arg0).equals(serializer.toXML(arg1));
		}
		else {
			result = false;
		}

		return result;
	}

	/**
	 * Compare the two collections.
	 * @param <T> the generic type
	 * @param msg the message
	 * @param arg0 the first object
	 * @param arg1 the second object
	 * @param comparator the comparator
	 */
	public static <T> void assertEquals(final String msg, final Collection<T> arg0,
	    final Collection<T> arg1, final Comparator<T> comparator) {
		boolean result;

		if (arg0 == null && arg1 == null) {
			result = true;
		}
		else if (arg0 != null && arg1 == null || arg0 == null && arg1 != null) {
			result = false;
		}
		else if (arg0 != null && arg1 != null) {
			result = arg1.size() == arg0.size();

			if (result) {
				final Iterator<T> ite0 = arg0.iterator();
				Iterator<T> ite1;
				T toSearch;
				boolean found = false;

				while (ite0.hasNext() && result) {
					toSearch = ite0.next();
					ite1 = arg1.iterator();

					while (ite1.hasNext() && !found) {
						found = comparator.compare(toSearch, ite1.next()) == 0;
					}

					result = found;
				}
			}
		}
		else {
			result = false;
		}

		if (!result) {
			assertEquals(msg, arg0, arg1);
		}
	}

	/**
	 * Compare the two objects using XStream.
	 * @param msg the message
	 * @param arg0 the first object
	 * @param arg1 the second object
	 */
	public static void assertEquals(final String msg, final Object arg0, final Object arg1) {
		if (arg0 == null && arg1 == null) {}
		else if (arg0 != null && arg1 == null || arg0 == null && arg1 != null) {}
		else if (arg0 != null && arg1 != null) {
			final XStream serializer = new XStream();

			serializer.setMode(XStream.NO_REFERENCES);

			Assert.assertEquals(msg, serializer.toXML(arg0), serializer.toXML(arg1));
		}
	}
}
